<?php
/**
 * 易优CMS
 * ============================================================================
 * 版权所有 2016-2028 海南赞赞网络科技有限公司，并保留所有权利。
 * 网站地址: http://www.eyoucms.com
 * ----------------------------------------------------------------------------
 * 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
 * ============================================================================
 * Author: 陈风任 <491085389@qq.com>
 * Date: 2020-05-22
 */

namespace weapp\Hupijiaopay\controller;

use think\Page;
use think\Db;
use app\common\controller\Weapp;
use weapp\Hupijiaopay\model\HupijiaopayModel;

/**
 * 插件的控制器
 */
class Hupijiaopay extends Weapp
{
    /**
     * 实例化模型
     */
    private $model;

    /**
     * 插件基本信息
     */
    private $weappInfo;

    /**
     * 构造方法
     */
    public function __construct(){
        parent::__construct();
        $this->model = new HupijiaopayModel;

        /*插件基本信息*/
        $this->weappInfo = $this->getWeappInfo();
        $this->assign('weappInfo', $this->weappInfo);
        /*--end*/
    }

    // 插件安装的前置操作
    public function beforeInstall()
    {
        // 判断是否已安装并且开启
        $personPay = Db::name('weapp')->where(['code' => 'PersonPay', 'status' => ['gt', 0]])->count();
        if (!empty($personPay)) $this->error("已启用【支付宝个人收款】插件，请先禁用或删除【支付宝个人收款】插件");
        
        // 安装前删除支付API中对应的数据
        if (!empty($this->weappInfo)) {
            $where = [
                'pay_mark' => $this->weappInfo['code'],
                'system_built' => 0
            ];
            Db::name('pay_api_config')->where($where)->delete();
        }
    }

    // 插件安装的后置操作
    public function afterInstall()
    {
        // 安装前添加支付API中对应的数据
        if (!empty($this->weappInfo)) {
            $PayApiData = [
                'pay_name'      => $this->weappInfo['name'],
                'pay_mark'      => $this->weappInfo['code'],
                'pay_info'      => '',
                'pay_terminal'  => '',
                'system_built'  => 0,
                'status'        => 1,
                'lang'          => $this->admin_lang,
                'add_time'      => getTime(),
                'update_time'   => getTime()
            ];
            Db::name('pay_api_config')->add($PayApiData);
        }
    }

    // 插件卸载的后置操作
    public function afterUninstall()
    {
        // 安装前删除支付API中对应的数据
        if (!empty($this->weappInfo)) {
            $where = [
                'pay_mark' => $this->weappInfo['code'],
                'system_built' => 0
            ];
            Db::name('pay_api_config')->where($where)->delete();
        }
    }

    // 插件启用的前置操作
    public function beforeEnable()
    {
        // 判断是否已安装并且开启
        $personPay = Db::name('weapp')->where(['code' => 'PersonPay', 'status' => ['gt', 0]])->count();
        if (!empty($personPay)) $this->error("已启用【支付宝个人收款】插件，请先禁用或删除【支付宝个人收款】插件");
    }

    // 插件启用的后置操作
    public function afterEnable()
    {
        // 启用插件后，将支付API中对应的数据更新为开启
        if (!empty($this->weappInfo)) {
            $where = [
                'pay_mark' => $this->weappInfo['code'],
                'system_built' => 0
            ];
            $update = [
                'status' => 1,
                'update_time' => getTime()
            ];
            Db::name('pay_api_config')->where($where)->update($update);
        }
    }

    // 插件禁用的后置操作
    public function afterDisable()
    {
        // 启用插件后，将支付API中对应的数据更新为关闭
        if (!empty($this->weappInfo)) {
            $where = [
                'pay_mark' => $this->weappInfo['code'],
                'system_built' => 0
            ];
            $update = [
                'status' => 0,
                'update_time' => getTime()
            ];
            Db::name('pay_api_config')->where($where)->update($update);
        }
    }

    // 支付配置
    public function index()
    {
        if (!empty($this->weappInfo)) {
            $where = [
                'pay_mark' => $this->weappInfo['code'],
                'system_built' => 0
            ];
            $Config = Db::name('pay_api_config')->where($where)->find();
            $this->UnifyAction($Config);
        }

        return $this->fetch('index');
    }

    // 加载支付配置数据到模板
    public function UnifyAction($Config = [])
    {
        $pay_info = !empty($Config['pay_info']) ? unserialize($Config['pay_info']) : [];
        $Config['pay_terminal'] = !empty($Config['pay_terminal']) ? unserialize($Config['pay_terminal']) : [];
        $pay_info['gateway_domain'] = !empty($pay_info['gateway_domain']) ? $pay_info['gateway_domain'] . '/payment/do.html' : '';
        $this->assign('Config', $Config);
        $this->assign('pay_info', $pay_info);
        return $this->fetch('index');
    }

    // 保存支付配置数据
    public function UnifySaveConfigAction($post = [])
    {
        if (empty($post['pay_info']['is_open_pay'])) {
            foreach ($post['pay_info'] as $key => $val) {
                $post['pay_info'][$key] = trim($val);
            }
            // 请填写至少一种支付配置
            if (empty($post['pay_info']['alipay_appid']) && empty($post['pay_info']['wechat_appid'])) $this->error('请填写至少一种支付配置');
            // 支付宝或微信支付配置
            if (!empty($post['pay_info']['wechat_appid']) && empty($post['pay_info']['wechat_appsecret'])) $this->error('请填写虎皮椒的微信AppSecret');
            if (!empty($post['pay_info']['alipay_appid']) && empty($post['pay_info']['alipay_appsecret'])) $this->error('请填写虎皮椒的支付宝AppSecret');
            // 支付网关配置
            if (empty($post['pay_info']['gateway_domain'])) $this->error('请填写支付网关');
        }

        if (!empty($post['pay_info']['gateway_domain'])) {
            $gateway_domain = $post['pay_info']['gateway_domain'];
            $index = strstr($gateway_domain, '/payment/do.html');
            $gateway_domain = !empty($index) ? str_replace('/payment/do.html', '', $gateway_domain) : $gateway_domain;
            $post['pay_info']['gateway_domain'] = $gateway_domain;
        }

        // 保存配置
        $update['pay_info'] = serialize($post['pay_info']);
        // $update['pay_terminal'] = !empty($post['pay_terminal']) ? serialize($post['pay_terminal']) : [];
        $update['update_time'] = getTime();
        $where = [
            'pay_id' => $post['pay_id'],
            'pay_mark' => $this->weappInfo['code'],
            'system_built' => 0
        ];
        $resultID = Db::name('pay_api_config')->where($where)->update($update);

        // 返回结果
        if (!empty($resultID)) {
            $this->success('保存成功');
        } else {
            $this->error('数据错误');
        }
    }

    // 获取支付二维码/URL等等
    public function UnifyGetPayAction($payInfo = [], $order = [], $returnUrl = null, $is_update = false, $pay_type = '')
    {
        // 如果没有传入配置则查询配置
        if (empty($payInfo)) {
            $payInfo = Db::name('pay_api_config')->where(['pay_mark' => 'Hupijiaopay'])->getField('pay_info');
            $payInfo = !empty($payInfo) ? unserialize($payInfo) : [];
        }

        // 是否传入指定支付类型则处理
        if (!empty($pay_type)) {
            $payInfo['pay_type'] = trim($pay_type);
            $payInfo['appid'] = !empty($payInfo[$pay_type . '_appid']) ? explode('_', $payInfo[$pay_type . '_appid'])[0] : '';
            $payInfo['appsecret'] = !empty($payInfo[$pay_type . '_appsecret']) ? explode('_', $payInfo[$pay_type . '_appsecret'])[0] : '';
        }

        // 参数处理
        if (empty($order['unified_number']) && !empty($order['order_code'])) $order['unified_number'] = trim($order['order_code']);
        if (empty($order['unified_amount']) && !empty($order['order_amount'])) $order['unified_amount'] = trim($order['order_amount']);

        // 拼装数组 
        $post_data = [
            'version'    => '1.1',
            'appid'      => $payInfo['appid'],
            'trade_order_id' => $order['unified_number'],
            'total_fee'  => $order['unified_amount'],
            'title'      => empty($is_update) ? '订单支付' : '检测支付配置',
            'time'       => time(),
            'notify_url' => url('plugins/Hupijiaopay/notify', [], true, true, 1, 1, 0),
            'return_url' => !empty($returnUrl) ? $returnUrl : url('user/Users/index'),
            'callback_url' => '',
            'plugins'    => str_replace("/", "-", str_replace(".", "-", $_SERVER['HTTP_HOST']) . ROOT_DIR),
            'nonce_str'  => str_shuffle(time()),
            'type'       => 'WAP',
            'wap_url'    => $_SERVER['HTTP_ORIGIN'],
            'wap_name'   => tpCache('web.web_name'),
            'lang'       => 'zh-cn',
            'payment'    => 'wechat',
            'attach'     => $order['transaction_type'] . '|,|' . $order['users_id'] . '|,|' . $payInfo['pay_type'] . '|,|hupijiaoPay',
            'modal'      => null,
        ];
        $post_data['hash'] = $this->generate_xh_hash($post_data, $payInfo['appsecret']);

        // 调用接口
        if (empty($payInfo['gateway_domain'])) $payInfo['gateway_domain'] = 'https://api.xunhupay.com';
        $post_url = $payInfo['gateway_domain'] . '/payment/do.html';
        $index = strstr($payInfo['gateway_domain'], '/payment/do.html');
        if (!empty($index)) $post_url = $payInfo['gateway_domain'];
        $data = json_decode($this->http_post($post_url, json_encode($post_data)), true);

        // 处理返回
        if ('success!' == $data['errmsg'] && (!empty($data['url_qrcode']) || !empty($data['url']))) {
            // 同步保存虎皮椒微信支付配置
            if (!empty($is_update)) {
                // 去除URL指定部分
                $index = strstr($payInfo['gateway_domain'], '/payment/do.html');
                if (!empty($index)) $payInfo['gateway_domain'] = str_replace('/payment/do.html', '', $payInfo['gateway_domain']);
                // 保存配置时默认开启虎皮椒支付功能
                $payInfo['is_open_pay'] = 0;
                // 删除多余的处理数据
                unset($payInfo['pay_type'], $payInfo['appid'], $payInfo['appsecret']);
                // 保存配置信息
                $where = [
                    'pay_mark' => $this->weappInfo['code'],
                    'system_built' => 0
                ];
                $update = [
                    'pay_info' => serialize($payInfo),
                    'update_time' => getTime(),
                ];
                Db::name('pay_api_config')->where($where)->update($update);
            }

            $result['url'] = null;
            $result['data'] = $data;
            return $result;
        } else {
            return false;
        }
    }

    // 查询订单支付状态
    public function OtherPayProcessing($payInfo = [], $unified_number = null)
    {
        // $unified_number = '20230705168852255317';
        // 调用订单查询接口参数
        $post_data = [
            'appid'     => $payInfo['appid'],
            'out_trade_order' => $unified_number,
            'time'      => time(),
            'nonce_str' => str_shuffle(time())
        ];
        $post_data['hash'] = $this->generate_xh_hash($post_data, $payInfo['appsecret']);

        // 发起查询并处理数据
        if (empty($payInfo['gateway_domain'])) $payInfo['gateway_domain'] = 'https://api.xunhupay.com';
        $post_url = $payInfo['gateway_domain'] . '/payment/query.html';
        $index = strstr($payInfo['gateway_domain'], '/payment/query.html');
        if (!empty($index)) $post_url = $payInfo['gateway_domain'];
        $data = json_decode($this->http_post($post_url, http_build_query($post_data)), true);
        $result = !empty($data['data']) ? $data['data'] : [];
        if (empty($result)) return false;

        // 返回结果
        if (!empty($result['out_trade_order']) && $result['out_trade_order'] == $unified_number) {
            if ('WP' == $result['status']) {
                // 未支付
                return '正在支付中...';
            } else if ('OD' == $result['status']) {
                // 已支付
                return $result;
            }
        }
    }

    // 虎皮椒hash方法
    private function generate_xh_hash($datas = [], $hashkey = null)
    {
        ksort($datas);
        reset($datas);

        $pre = [];
        foreach ($datas as $key => $data){
            if (is_null($data) || $data === '') continue;
            if ($key == 'hash') continue;
            $pre[$key] = stripslashes($data);
        }

        $arg   = '';
        $qty   = count($pre);
        $index = 0;
        foreach ($pre as $key => $val){
            $arg .= "$key=$val";
            if ($index++ < ($qty-1)) $arg .= "&";
        }

        return md5($arg . $hashkey);
    }

    // 接口调用方法
    private function http_post($url = null, $post_data = [])
    {
        if (!function_exists('curl_init')) {
            $this->error('php未安装curl组件');
            // throw new \Exception('php未安装curl组件', 500);
        }
        
        $protocol = (!empty($_SERVER ['HTTPS']) && $_SERVER ['HTTPS'] !== 'off' || $_SERVER ['SERVER_PORT'] == 443) ? "https://" : "http://";

        $siteurl = $protocol . $_SERVER['HTTP_HOST'];
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_REFERER,$siteurl);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        $response = curl_exec($ch);
        $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        if ($httpStatusCode != 200) {
            $this->error($response);
            // throw new \Exception("invalid httpstatus:{$httpStatusCode} ,response:$response,detail_error:".$error,$httpStatusCode);
        }

        return $response;
    }
}